//
//  LanBDepositer.m
//  LanBKit_Example
//
//  Created by v on 2020/11/6.
//  Copyright © 2020 v. All rights reserved.
//

#import "LanBDepositer.h"
#import <LanBKit/LanBCore.h>
#import <Base64.h>
#import <MJExtension/MJExtension.h>

/**
 1：微信App原生参数，实际的参数是一个json对象，包含调起App所需的参数
 2：微信小程序原生参数，实际的参数是一个json对象，包含调起小程序所需的参数
 3：阿里App原生参数，
 4：URL，表示的参数是一个以http或https开头的url地址
 5：表示的参数是一个完整的HTML页面
 6：表示的参数是一个HTML表单代码
 7：表示的参数是微信shcema (weixin://)开头的字符串
 8：表示的参数是阿里schema(alipay://)开头的字符串
 */
typedef NS_ENUM(NSUInteger, LanBDepositType) {
    LanBDepositType_wxObj           = 1,
    LanBDepositType_wxMiniObj       = 2,
    LanBDepositType_aliObj          = 3,
    LanBDepositType_URI             = 4,
    LanBDepositType_HtmlString      = 5,
    LanBDepositType_HtmlForm        = 6,
    LanBDepositType_wxScheme        = 7,
    LanBDepositType_aliScheme       = 8,
};

/*! wx 分享小程序类型
 *
 */
typedef NS_ENUM(NSUInteger, LanB_WXMiniProgramType) {
    LanB_WXMiniProgramTypeRelease = 0, //**< 正式版  */
    LanB_WXMiniProgramTypeTest    = 1, //**< 开发版  */
    LanB_WXMiniProgramTypePreview = 2, //**< 体验版  */
};

@interface LanBDepositer ()
@property (nonatomic, copy) openUrlBlock openUrlBlock;
@property (nonatomic, strong) NSString *aliScheme;
@property (nonatomic, strong) NSString *wxH5Scheme;
@property (nonatomic, strong) LanBDepositWebController *web;
@end

@implementation LanBDepositer

/** 返回单例  */
static LanBDepositer *shareInstance;
+ (instancetype)shared
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!shareInstance) {
            shareInstance = [[self alloc] init];
        }
    });
    return shareInstance;
}

- (void)lanb_setAliScheme:(NSString *)aliScheme wxH5Scheme:(NSString *)wxH5Scheme
{
    self.aliScheme  = aliScheme;
    self.wxH5Scheme = wxH5Scheme;
}

- (LanBDepositWebController *)lanb_depositWithInfo:(NSString *)info openUrlBlock:(openUrlBlock)block
{
    self.web                      = nil;
    self.openUrlBlock             = block;
    
    NSDictionary *depositDic = [info mj_JSONObject];
    
    NSInteger type = [depositDic[@"type"] integerValue];
    NSString *data = depositDic[@"info"];
    
    switch (type) {
        case LanBDepositType_wxObj:
            {
                NSDictionary *map  = data.mj_JSONObject;
                NSString     *link = [self _we_chat_deposit_Data:map];
                [self _openLink:link];
            }
            break;
        case LanBDepositType_wxMiniObj:
            {
                NSDictionary *map  = data.mj_JSONObject;
                NSString     *link = [self _we_chat_depositMiniProgram_Data:map];
                [self _openLink:link];
            }
            break;
        case LanBDepositType_aliObj:
            {
                NSString *link = [self _ali_deposit_Data:data fromScheme:self.aliScheme];
                [self _openLink:link];
            }
            break;
        case LanBDepositType_URI:
            {
                self.wxH5Scheme = depositDic[@"referer"] ? depositDic[@"referer"] : self.wxH5Scheme;
                LanBDepositWebController *webController = [[LanBDepositWebController alloc] initWithUrlString:data];
                [webController view];
                self.web = webController;
            }
            break;
        case LanBDepositType_HtmlString:
            {
                LanBDepositWebController *webController = [[LanBDepositWebController alloc] initWithHtmlString:data];
                [webController view];
                self.web = webController;
            }
            break;
        case LanBDepositType_HtmlForm:
            {
                if ( [data hasPrefix:@"<form"] ) {
                    data = [NSString stringWithFormat:@"<html><head></head><body>%@</body></html>", data];
                    LanBDepositWebController *webController = [[LanBDepositWebController alloc] initWithHtmlString:data];
                    [webController view];
                    self.web = webController;
                }else{
                    self.openUrlBlock(NO, nil);
                }
            }
            break;
        case LanBDepositType_wxScheme:
            {
                [self _openLink:data];
            }
            break;
        case LanBDepositType_aliScheme:
            {
                if ([data hasPrefix:@"alipay"] || [data hasPrefix:@"alipays"]) {
                    // url decode
                    NSString *decodeUrl = data.stringByRemovingPercentEncoding;
                    NSString *baseUrl = decodeUrl.lanB_baseUrl;
                    NSString *query   = decodeUrl.lanB_query;
                    NSMutableDictionary *paramDic = [query.mj_JSONObject mutableCopy];
                    if ([paramDic isKindOfClass:NSDictionary.class] && paramDic[@"fromAppUrlScheme"]) { // 替换 ali 原生 scheme
                        paramDic[@"fromAppUrlScheme"] = self.aliScheme;
                        NSString *link = [NSString stringWithFormat:@"%@?%@", baseUrl, paramDic.mj_JSONString];
                        // url encode
                        data = [link stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
                    }
                    [self _openLink:data];
                }
            }
            break;
        default:
            break;
    }
    
    return self.web;
}

#pragma mark - private
- (void)_openLink:(NSString*)link
{
    NSURL *urlLink = [NSURL URLWithString:link];
    if ([UIApplication.sharedApplication canOpenURL:urlLink]) {
        if (@available(iOS 10.0, *)) {
            [UIApplication.sharedApplication openURL:urlLink options:@{} completionHandler:^(BOOL success) {
                if (self.openUrlBlock) {
                    self.openUrlBlock(success, urlLink);
                }
            }];
        } else {
            BOOL success = [UIApplication.sharedApplication openURL:urlLink];
            if (self.openUrlBlock) {
                self.openUrlBlock(success, urlLink);
            }
        }
        return;
    }
}

/**
 ali 原生
 */
- (NSString *)_ali_deposit_Data:(NSString *)dataString fromScheme:(NSString *)fromScheme {
    NSMutableString *result = [NSMutableString string];
    // {"requestType":"SafePay","fromAppUrlScheme":"%@","dataString":"%@"}
    NSString *targetStr1 = [@"eyJyZXF1ZXN0VHlwZSI6IlNhZmVQYXkiLCJmcm9tQXBwVXJsU2NoZW1lIjoiJUAiLCJkYXRhU3RyaW5nIjoiJUAifQ==" base64DecodedString];
    // alipay://alipayclient/?
    NSString *targetStr2 = [@"YWxpcGF5Oi8vYWxpcGF5Y2xpZW50Lz8=" base64DecodedString];
    NSString *depositStr = [NSString stringWithFormat:targetStr1, fromScheme?:@"", dataString];
    depositStr           = [self _urlEncodeWithString:depositStr];
    [result appendString:[targetStr2 stringByAppendingString:depositStr]];
    return result;
}

- (NSString *)_urlEncodeWithString:(NSString *)string {
    return [string stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
}

- (NSString *)_urlEncodeURIComponent:(NSString *)string {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (__bridge CFStringRef)string, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding)));
    #pragma clang diagnostic pop
}

/**
 wx 原生
 */
- (NSString *)_we_chat_deposit_Data:(NSDictionary *)info {
    NSMutableString *result = [NSMutableString string];
    if ([info isKindOfClass:NSDictionary.class]) {
        [result appendFormat:@"weixin://app/%@/pay/?", [info valueForKey:@"appid"]];
        [result appendFormat:@"nonceStr=%@&package=Sign%%3DWXPay&", [info valueForKey:@"noncestr"]];
        [result appendFormat:@"partnerId=%@&", [info valueForKey:@"partnerid"]];
        [result appendFormat:@"prepayId=%@&", [info valueForKey:@"prepayid"]];
        [result appendFormat:@"timeStamp=%@&", [info valueForKey:@"timestamp"]];
        [result appendFormat:@"sign=%@&signType=SHA1", [info valueForKey:@"sign"]];
    }
    return result;
}

/**
 wx mini
*/
- (NSString *)_we_chat_depositMiniProgram_Data:(NSDictionary *)info {
    NSString *result;
    if ([info isKindOfClass:NSDictionary.class]) {
        NSString *             appid           = info[@"appId"];
        NSString *             ghId            = info[@"userName"];
        NSString *             path            = info[@"path"];
        LanB_WXMiniProgramType miniProgramType = [info[@"miniProgramType"] integerValue];
        result = [self _we_chat_deposit_miniProgramWithAppId:appid ghId:ghId path:path type:miniProgramType];
    }
    return result;
}

- (NSString*)_we_chat_deposit_miniProgramWithAppId:(NSString *)appid ghId:(NSString *)username path:(NSString *)path type:(LanB_WXMiniProgramType)miniProgramtype {
    NSString *mPath = [path stringByReplacingOccurrencesOfString:@"/" withString:@"%2F"];
    NSString *url   = [NSString stringWithFormat:@"weixin://app/%@/jumpWxa/?userName=%@&path=%@&miniProgramType=%lu&extMsg=", appid, username, mPath, (unsigned long)miniProgramtype];
    return url;
}

@end
